part of '../../flutter_ns_ble.dart';




/// 文件头20个字节为标识
class EcgFile implements FileSystemEntity {
  late RandomAccessFile _randomAccessFile;
  late File _file;

  final int _magicCode = 0xbc;
  final int _headerSize = 20;

  static final int VERSION = 2;

  EcgFile(String path) {
    _file = File(path);
    _randomAccessFile = _file.openSync(mode: FileMode.append);
  }

  Future<EcgFile> create({
    bool recursive = false,
    bool exclusive = false,
  }) async {
    await _file.create(recursive: recursive, exclusive: exclusive);

    await _randomAccessFile.setPosition(0);
    await _randomAccessFile.writeByte(_magicCode);
    await _randomAccessFile.writeByte(VERSION);
    return EcgFile(_file.path);
  }

  void createSync({bool recursive = false, bool exclusive = false}) {
    _file.createSync(recursive: recursive, exclusive: exclusive);

    _randomAccessFile.setPositionSync(0);
    _randomAccessFile.writeByteSync(_magicCode);
    _randomAccessFile.writeByteSync(VERSION);
  }

  int get version {
    _randomAccessFile.setPositionSync(1);
    return _randomAccessFile.readByteSync();
  }

  int _writeCount = 0;

  Future<EcgFile> writeFrom(
    List<double> points, [
    int start = 0,
    int? end,
  ]) async {
    await _randomAccessFile.setPosition(_writeCount * 4 + _headerSize);
      List<int> buffer = List.empty(growable: true);
      for (double point in points.sublist(start, end)) {
        var byteData = ByteData(4);
        byteData.setFloat32(0, point, Endian.big);
        var data = byteData.buffer.asUint8List();
        buffer.addAll(data);
        _writeCount += 1;
      }
      await _randomAccessFile.writeFrom(buffer);
      return this;
  }

  void writeFromSync(List<double> points, [int start = 0, int? end]) {
    _randomAccessFile.setPositionSync(_writeCount * 4 + _headerSize);
      List<int> buffer = List.empty(growable: true);
      for (double point in points.sublist(start, end)) {
        var byteData = ByteData(4);
        byteData.setFloat32(0, point, Endian.big);
        var data = byteData.buffer.asUint8List();
        buffer.addAll(data);
        _writeCount += 1;
      }
      _randomAccessFile.writeFromSync(buffer);
  }

  Future<double> read({int start = 0}) async {
    await _randomAccessFile.setPosition(start * 4 + _headerSize);
    int length = 4;
    Uint8List buffer = Uint8List(length);
    await _randomAccessFile.readInto(buffer);
    final byteData = buffer.buffer.asByteData();
    double num = byteData.getFloat32(0);
    return num;
  }

  double readSync({int start = 0}) {
    _randomAccessFile.setPositionSync(start * 4 + _headerSize);
    int length = 4;
    Uint8List buffer = Uint8List(length);
    _randomAccessFile.readIntoSync(buffer);
    final byteData = buffer.buffer.asByteData();
    double num = byteData.getFloat32(0);
    return num;
  }

  Future<List<double>> readList({int start = 0, int count = 1}) async {
    await _randomAccessFile.setPosition(start * 4 + _headerSize);
    int length = count * 4;
    Uint8List buffer = Uint8List(length);
    int l = await _randomAccessFile.readInto(buffer);
    final byteData = buffer.buffer.asByteData();
    List<double> points = List.empty(growable: true);
    for (int i = 0; i < l / 4; i++) {
      int byteOffset = i * 4;
      double num = byteData.getFloat32(byteOffset);
      points.add(num);
    }
    return points;
  }

  List<double> readListSync({int start = 0, int count = 1}) {
    _randomAccessFile.setPositionSync(start * 4 + _headerSize);
    int length = count * 4;
    Uint8List buffer = Uint8List(length);
    int l = _randomAccessFile.readIntoSync(buffer);
    final byteData = buffer.buffer.asByteData();
    List<double> points = List.empty(growable: true);
    for (int i = 0; i < l / 4; i++) {
      int byteOffset = i * 4;
      double num = byteData.getFloat32(byteOffset);
      points.add(num);
    }
    return points;
  }

  /// [count] 每次读取多少个点
  Stream<List<double>> readAll() async* {
    var stream = _file.openRead(_headerSize);
    await for (var data in stream) {
      List<double> points = List.empty(growable: true);
      final byteData = Uint8List.fromList(data).buffer.asByteData();
      for (int i = 0; i < data.length / 4; i++) {
        int byteOffset = i * 4;
        double num = byteData.getFloat32(byteOffset);
        points.add(num);
      }
      yield points;
    }
  }

  /// 数据长度
  Future<int> pointLength() async {
    int length = await _file.length();
    return (length - _headerSize) ~/ 4;
  }

  /// 数据长度
  int pointLengthSync() {
    int length = _file.lengthSync();
    return (length - _headerSize) ~/ 4;
  }

  @override
  File get absolute => _file.absolute;

  @override
  Future<FileSystemEntity> delete({bool recursive = false}) async {
   return _file.delete(recursive: recursive);
  }

  @override
  void deleteSync({bool recursive = false}) {
    _file.deleteSync(recursive: recursive);
  }

  @override
  Future<bool> exists() {
    return _file.exists();
  }

  @override
  bool existsSync() {
    return _file.existsSync();
  }

  @override
  bool get isAbsolute => _file.isAbsolute;

  @override
  Directory get parent => _file.parent;

  @override
  String get path => _file.path;

  @override
  Future<EcgFile> rename(String newPath) async {
    await _file.rename(newPath);
    return EcgFile(newPath);
  }

  @override
  EcgFile renameSync(String newPath) {
    _file.renameSync(newPath);
    return EcgFile(newPath);
  }

  @override
  Future<String> resolveSymbolicLinks() {
    return _file.resolveSymbolicLinks();
  }

  @override
  String resolveSymbolicLinksSync() {
    return _file.resolveSymbolicLinksSync();
  }

  @override
  Future<FileStat> stat() {
    return _file.stat();
  }

  @override
  FileStat statSync() {
    return _file.statSync();
  }

  @override
  Uri get uri => _file.uri;

  @override
  Stream<FileSystemEvent> watch({
    int events = FileSystemEvent.all,
    bool recursive = false,
  }) {
    return _file.watch(events: events, recursive: recursive);
  }

  Future<void> close() async {
    await _randomAccessFile.close();
  }

  void closeSync() {
    _randomAccessFile.closeSync();
  }

  Future<int> length() {
    return _file.length();
  }

  int lengthSync() {
    return _file.lengthSync();
  }

  Future<RandomAccessFile> flush() async {
    return _randomAccessFile.flush();
  }

  void flushSync() {
    _randomAccessFile.flushSync();
  }

}

// void main(List<String> args) async {
//   String path = "/Users/tom/Downloads/test.ecg";
//   var ecgFile = EcgFile(path);
//   await ecgFile.create();
//   print("version:${ecgFile.version}");
//   await ecgFile.writeFrom([100, 1]);
//   print("${ecgFile.readListSync(start: 1)}");
// }
